package com.ihg.hiex.admin.web.controller.session;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.demo2do.core.entity.exception.BusinessException;
import com.demo2do.core.entity.page.Page;
import com.demo2do.core.entity.result.HttpResult;
import com.demo2do.core.web.interceptor.MenuSetting;
import com.demo2do.core.web.resolver.Preloading;
import com.demo2do.core.web.utils.WebUtils;
import com.ihg.hiex.admin.entity.security.Login;
import com.ihg.hiex.admin.entity.session.FacilitatorConferenceRoom;
import com.ihg.hiex.admin.handler.AccountUploadHandler;
import com.ihg.hiex.admin.handler.FileHandler;
import com.ihg.hiex.admin.handler.support.FileStorage;
import com.ihg.hiex.admin.service.DataService;
import com.ihg.hiex.admin.service.session.SessionService;
import com.ihg.hiex.admin.web.resolver.Secure;
import com.ihg.hiex.entity.session.Session;
import com.ihg.hiex.entity.session.Status;
import com.ihg.hiex.entity.session.participator.SessionFacilitator;
import com.ihg.hiex.entity.user.Assessor;
import com.ihg.hiex.entity.user.Delegate;

/**
 * 
 * @author Guangli Yan
 *
 */
@Controller
@RequestMapping("/session-settings")
@MenuSetting("menu-settings")
public class SessionSettingController {
    
    private static final Logger logger = LoggerFactory.getLogger(SessionSettingController.class);
    
    @Autowired
    private SessionService sessionService;
    
    @Autowired
    private AccountUploadHandler accountUploadHandler;
    
    @Autowired
    private FileHandler fileHandler;

    @Autowired
    @Qualifier("dataService")
    private DataService<SessionFacilitator> sessionFacilitatorService;
    
    /**
     * list session by page
     * 
     * @param login
     * @param request
     * @param page
     * @return
     */
    @RequestMapping(value = "", method = RequestMethod.GET)
    @MenuSetting("submenu-session-setting-list")
    public ModelAndView list(@Secure Login login, HttpServletRequest request, Page page) {

        ModelAndView modelAndView = new ModelAndView("settings/session/session-setting-list");
        
        int totals = sessionService.count(login, Status.NOTSTARTED);
        if (totals > 0) {

            List<Session> sessions = sessionService.list(login, Status.NOTSTARTED, page.with(totals));
            modelAndView.addObject("sessions", sessions);
            
            modelAndView.addObject("page", page); 
            modelAndView.addObject("queryString", WebUtils.extractQueryString(request, "page", "filter"));
            
        }
        
        return modelAndView;
        
    }
    
    /**
     * session view
     * 
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/{sessionId}", method = RequestMethod.GET)
    @MenuSetting("submenu-session-setting-list")
    public ModelAndView view(@PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("settings/session/view/session-setting-view");
        
        // 1. load session
        Session session = sessionService.load(sessionId);
        modelAndView.addObject("session", session);
        
        // 2. list session's facilitator
        List<SessionFacilitator> facilitators = sessionService.listFacilitator(session);
        modelAndView.addObject("facilitators", facilitators);
        
        // 3. list session's all assessors
        List<Assessor> assessors = sessionService.listAssessor(session);
        modelAndView.addObject("assessors", assessors);
        
        // 4. list session's all delegates
        List<Delegate> delegates = sessionService.listDelegate(session);
        modelAndView.addObject("delegates", delegates);
        
        return modelAndView;
        
    }

    /**
     * create session page
     * 
     * @return
     */
    @RequestMapping(value = "/create", method = RequestMethod.GET)
    @MenuSetting("submenu-add-sessions-management")
    public ModelAndView create() {
        ModelAndView modelAndView = new ModelAndView("settings/session/session-setting-create");
        return modelAndView;
    }

    /**
     * create session
     * 
     * @param login
     * @param session
     * @param assessorWechatGroupFile
     * @param delegateWechatGroupFile
     * @param assessorFile
     * @param delegateFile
     * @return
     */
    @RequestMapping(value = "", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ModelAndView onCreate(@Secure Login login, Session session, 
                                 @RequestParam("assessorWechatGroupFile") MultipartFile assessorWechatGroupFile,
                                 @RequestParam("delegateWechatGroupFile") MultipartFile delegateWechatGroupFile,
                                 @RequestParam("assessors") MultipartFile assessorFile,
                                 @RequestParam("delegates") MultipartFile delegateFile) {
        
        ModelAndView modelAndView = new ModelAndView("redirect:/session-settings");
        
        try {
            
            // parse file to assessors & delegates
            List<Assessor> assessors = accountUploadHandler.assessorUpload(assessorFile.getInputStream());
            List<Delegate> delegates = accountUploadHandler.delegateUpload(delegateFile.getInputStream());
            
            // save assessorWechatGroup & delegateWechatGroup
            FileStorage assessorFileStorage = new FileStorage("wechat/", session.getName() + "_assessor_wechat_group", FilenameUtils.getExtension(assessorWechatGroupFile.getOriginalFilename()));
            String assessorWechatGroup = fileHandler.save(assessorFileStorage, assessorWechatGroupFile.getInputStream());
            FileStorage delegateFileStorage = new FileStorage("wechat/", session.getName() + "_delegate_wechat_group", FilenameUtils.getExtension(delegateWechatGroupFile.getOriginalFilename()));
            String delegateWechatGroup = fileHandler.save(delegateFileStorage, delegateWechatGroupFile.getInputStream());

            // create session
            sessionService.create(session, assessors, delegates, assessorWechatGroup, delegateWechatGroup, login.getId(), login.getName());
            
        } catch (BusinessException e) {
            
            logger.error("onCreate - create fail, exception [{}]", e.getMessage());
            modelAndView.setViewName("settings/session/session-setting-create");
            modelAndView.addObject("errorMessage", e.getMessage());
            return modelAndView;
            
        } catch (Exception e) {
            
            logger.error("onCreate - create fail, exception [{}]", e);
            modelAndView.setViewName("settings/session/session-setting-create");
            modelAndView.addObject("errorMessage", "create session fail");
            return modelAndView;
            
        }
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/{sessionId}/re-upload", method = RequestMethod.GET)
    public ModelAndView reUpload(@PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("settings/session/view/session-re-upload");
        
        modelAndView.addObject("sessionId", sessionId);
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param login
     * @param session
     * @param assessorFile
     * @param delegateFile
     * @return
     */
    @RequestMapping(value = "/{sessionId}/re-upload", method = RequestMethod.POST)
    public ModelAndView onReUpload(@Secure Login login, 
                                   @Preloading("sessionId") Session session,
                                   @RequestParam("assessors") MultipartFile assessorFile,
                                   @RequestParam("delegates") MultipartFile delegateFile) {
        
        ModelAndView modelAndView = new ModelAndView("redirect:/session-settings/" + session.getId());
        
        try {
            
            // 1. parse file to assessors & delegates
            List<Assessor> assessors = accountUploadHandler.assessorUpload(assessorFile.getInputStream());
            List<Delegate> delegates = accountUploadHandler.delegateUpload(delegateFile.getInputStream());
            
            // 2. save assessors/delegates and update session
            sessionService.reUpload(session, assessors, delegates, login.getId(), login.getName());

        } catch (BusinessException e) {
            
            logger.error("onReUpload - upload fail, exception [{}]", e.getMessage());
            modelAndView.setViewName("settings/session/view/session-setting-view");
            modelAndView.addObject("session", session);
            modelAndView.addObject("errorMessage", e.getMessage());
            return modelAndView;
            
        } catch (Exception e) {
            
            logger.error("onReUpload - upload fail, exception [{}]", e);
            modelAndView.setViewName("settings/session/view/session-setting-view");
            modelAndView.addObject("session", session);
            modelAndView.addObject("errorMessage", "reUpload fail");
            return modelAndView;
            
        }
        
        return modelAndView;
        
    }

    /**
     * start view.
     * 
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/{sessionId}/start", method = RequestMethod.GET)
    public ModelAndView start(@PathVariable("sessionId") Long sessionId) {

        ModelAndView modelAndView = new ModelAndView("settings/session/session-setting-start");
        
        modelAndView.addObject("sessionId", sessionId);

        return modelAndView;
    }

    /**
     * start session
     * 
     * @param login
     * @param session
     * @return
     */
    @RequestMapping(value = "/{sessionId}/start", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onStart(@Secure Login login,
                                            @Preloading("sessionId") Session session) {

        HttpResult httpResult = new HttpResult();

        try {
            
            sessionService.start(session, login.getId(), login.getName());
            
            httpResult.success().message("开始成功");

        } catch (Exception e) {
            httpResult.fail("500").message("开始失败");
            logger.error("#onStart() - start fail, exception is [{}]", e);
        }

        return httpResult;
        
    }
        
    /**
     * edit view.
     * 
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/{sessionId}/edit", method = RequestMethod.GET)
    public ModelAndView edit(@PathVariable("sessionId") Long sessionId) {

        ModelAndView modelAndView = new ModelAndView("settings/session/view/session-setting-edit");
        
        Session session = sessionService.load(sessionId);
        modelAndView.addObject("session", session);
        
        return modelAndView;
    }

    /**
     * edit.
     * 
     * @param login
     * @param session
     * @return
     */
    @RequestMapping(value = "/{sessionId}", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onEdit(@Secure Login login, @Preloading("sessionId") Session session) {

        HttpResult httpResult = new HttpResult();

        try {
            
            sessionService.edit(session, login.getId(), login.getName());
            
            httpResult.success().message("修改成功");

        } catch (Exception e) {
            httpResult.fail("500").message("修改失败");
            logger.error("#onEdit() - edit session fail, exception is [{}]", e);
        }

        return httpResult;
        
    }
    
    /**
     * 
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/{sessionId}/delete", method = RequestMethod.GET)
    public ModelAndView delete(@PathVariable("sessionId") Long sessionId) {

        ModelAndView modelAndView = new ModelAndView("settings/session/session-setting-delete");
        
        modelAndView.addObject("sessionId", sessionId);

        return modelAndView;
        
    }

    /**
     * 
     * @param login
     * @param session
     * @return
     */
    @RequestMapping(value = "/{sessionId}/delete", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onDelete(@Secure Login login,
                                             @Preloading("sessionId") Session session) {

        HttpResult httpResult = new HttpResult();

        try {
            
            sessionService.delete(session, login.getId(), login.getName());
            httpResult.success().message("删除成功");

        } catch (Exception e) {
            httpResult.fail("500").message("删除失败");
            logger.error("#onDelete() - delete fail, exception is [{}]", e);
        }

        return httpResult;
    }

    /**
     * add session facilitator
     * 
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/{sessionId}/facilitators/create", method = RequestMethod.GET)
    public ModelAndView createFacilitator(@PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("settings/session/view/session-facilitator-create");
        
        modelAndView.addObject("sessionId", sessionId);
        
        return modelAndView;
        
    }
    
    /**
     * on add session facilitator
     * 
     * @param sessionId
     * @param facilitator
     * @param conferenceRoom
     * @return
     */
    @RequestMapping(value = "/{sessionId}/facilitators", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onCreateFacilitator(@PathVariable("sessionId") Long sessionId,
                                                        SessionFacilitator facilitator,
                                                        FacilitatorConferenceRoom conferenceRoom) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Session session = sessionService.load(sessionId);
            sessionService.createFacilitator(session, facilitator, conferenceRoom);
            
            httpResult.success().message("添加主讲师成功");
            
        } catch (Exception e) {
            httpResult.fail("500").message("添加主讲师失败");
            logger.error("#onCreateFacilitator() - create fail, exception is [{}]", e);
        }
        
        return httpResult;
        
    }
    
    /**
     * 
     * @param sessionId
     * @param facilitatorId
     * @return
     */
    @RequestMapping(value = "/{sessionId}/facilitators/{facilitatorId}/delete", method = RequestMethod.GET)
    public ModelAndView deleteFacilitator(@PathVariable("sessionId") Long sessionId,
                                          @PathVariable("facilitatorId") Long facilitatorId) {
        
        ModelAndView modelAndView = new ModelAndView("settings/session/view/session-facilitator-delete");
        
        modelAndView.addObject("sessionId", sessionId);
        modelAndView.addObject("facilitatorId", facilitatorId);
        
        return modelAndView;
        
    }
    
    /**
     * delete session facilitator
     * 
     * @param facilitatorId
     * @return
     */
    @RequestMapping(value = "/{sessionId}/facilitators/{facilitatorId}", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onDeleteFacilitator(@PathVariable("facilitatorId") Long facilitatorId) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            sessionFacilitatorService.delete(SessionFacilitator.class, facilitatorId);
            
            httpResult.success().message("删除主讲师成功");
            
        } catch (Exception e) {
            httpResult.fail("500").message("删除主讲师失败");
            logger.error("#onDeleteFacilitator() - create fail, exception is [{}]", e);
        }
        
        return httpResult;
        
    }
    
}
